import pandas as pd
from docx import Document
from docx.shared import Pt, RGBColor, Cm, Inches

from utils.analysis.sem.sem_r import SEM
from utils.analysis.common.mediation_common_class import SEMRelationConfig, SEMResult
from utils.report.base import create_table, delete_table_first_last_row, set_cell_border, format_table


def _generate_report(data, document, table_count, name_dict):
    s = "、".join(list(data.item_dict.keys()))
    p1 = (
        f"根据上述研究结果，在结构方程模型中，存在{len(data.item_dict.keys())}个潜在变量，{s}。"
        f"有13个观察变量对应{len(data.item_dict.keys())}个潜在变量。"
        f"问卷收集的数据导入到AMOS26.0软件中，应用最大似然法得到的模型拟合参数如图所示。"
    )
    document.add_paragraph(p1)  # 插入段落
    p2 = f"首先检验了验证因子分析量表的模型拟合。将问卷收集的数据导入AMOS26软件，应用最大似然法得到的模型拟合参数如表所示。"
    document.add_paragraph(p2)  # 插入段落
    table1 = _generate_table1(data, document, table_count)  # 表1
    p3 = (
        f"在进行路径分析之前，首先对模型的拟合情况进行分析，由上表可知，CMIN/DF值为{convert_str_to_float_3(data.fi_value.cmin_df)}，"
        f"小于3；RMSEA值为{convert_str_to_float_3(data.fi_value.rmsea)}，小于0.08；NFI	、IFI、TLI、CFI、GFI均大于0.9，"
        f"说明模型模型拟合度良好。"
    )
    document.add_paragraph(p3)  # 插入段落
    table2 = _generate_table2(data, document, table_count, name_dict)  # 表2
    last_str = ""
    for k, v in data.item_dict.items():
        have_influence = "有" if v.p < 0.05 else "没有"
        std_value_influence = "正向" if v.std_all < 0.05 else "负向"
        lor = "<" if v.p < 0.05 else ">"
        last_str += (
            f"从{name_dict.get(v.to_name)}对{name_dict.get(v.from_name)}的假设来看，"
            f"{name_dict.get(v.to_name)}对{name_dict.get(v.from_name)}{have_influence}显著的{std_value_influence}影响，"
            f"标准化路径系数为{convert_str_to_float_3(v.std_all)}（p={convert_str_to_float_3(v.p)}，p{lor}0.05）；")
    p4 = (
        f"在拟合指标分析证明结构方程模型的有效性后，对模型路径进行了分析。本研究使用AMOS26.0软件对研究模型中的假设关系进行检验。"
        f"具体假设检验结果见上表。由路径分析结果可知，{last_str}")
    document.add_paragraph(p4)  # 插入段落
    return


def _generate_table1(data, document, table_count):
    # 新建表格
    init_rows = 4
    init_cols = 11
    # table = document.add_table(rows=init_rows, cols=init_cols)
    table = create_table(document, init_rows, init_cols)
    # 1. 填充1-3行
    # 填充第一行表头
    row = table.rows[0]  # 表格
    f_cell = None
    for i in range(init_cols):  # 合并单元格
        if i == 0:
            f_cell = table.cell(0, 0)
        else:
            f_cell.merge(table.cell(0, i))
    frequency_table_name = ""
    row.cells[0].text = frequency_table_name + '验证因子分析的模型拟合'
    # 填充第二行
    table.cell(1, 0).text = "模型拟合"
    table.cell(1, 1).text = "CMIN"
    table.cell(1, 2).text = "DF"
    table.cell(1, 3).text = "CMIN/DF"
    table.cell(1, 4).text = "NFI"
    table.cell(1, 5).text = "RFI"
    table.cell(1, 6).text = "IFI"
    table.cell(1, 7).text = "TLI"
    table.cell(1, 8).text = "CFI"
    table.cell(1, 9).text = "GFI"
    table.cell(1, 10).text = "RMSEA"

    # 填充第四行
    table.cell(3, 0).text = "判定值"
    table.cell(3, 1).text = ""
    table.cell(3, 2).text = ""
    table.cell(3, 3).text = "<3"
    table.cell(3, 4).text = ">0.9"
    table.cell(3, 5).text = ">0.9"
    table.cell(3, 6).text = ">0.9"
    table.cell(3, 7).text = ">0.9"
    table.cell(3, 8).text = ">0.9"
    table.cell(3, 9).text = ">0.9"
    table.cell(3, 10).text = "<0.08"

    # 填充第三行
    table.cell(2, 0).text = "拟合结果"
    table.cell(2, 1).text = convert_str_to_float_3(data.fi_value.cmin)
    table.cell(2, 2).text = convert_str_to_float_3(data.fi_value.df_value)
    table.cell(2, 3).text = convert_str_to_float_3(data.fi_value.cmin_df)
    table.cell(2, 4).text = convert_str_to_float_3(data.fi_value.nfi)
    table.cell(2, 5).text = convert_str_to_float_3(data.fi_value.rfi)
    table.cell(2, 6).text = convert_str_to_float_3(data.fi_value.ifi)
    table.cell(2, 7).text = convert_str_to_float_3(data.fi_value.tli)
    table.cell(2, 8).text = convert_str_to_float_3(data.fi_value.cfi)
    table.cell(2, 9).text = convert_str_to_float_3(data.fi_value.gfi)
    table.cell(2, 10).text = convert_str_to_float_3(data.fi_value.rmsea)
    format_table(table)
    add_three_lines_table1(table)
    return table


def add_three_lines_table1(table):
    delete_table_first_last_row(table)
    first_row = table.rows[0]
    second_row = table.rows[1]
    for cell in first_row.cells:
        set_cell_border(cell, top={"sz": 12, "val": "single", "color": "#000000", "space": "0"})
    for cell in second_row.cells:
        set_cell_border(cell, top={"sz": 4, "color": "#000000", "val": "single", "space": "0"})
    last_row = table.rows[-1]
    for cell in last_row.cells:
        set_cell_border(cell, bottom={"sz": 12, "val": "single", "color": "#000000", "space": "0"})
    return


def add_three_lines_table2(table):
    delete_table_first_last_row(table)
    first_row = table.rows[0]
    second_row = table.rows[1]
    for cell in first_row.cells:
        set_cell_border(cell, top={"sz": 12, "val": "single", "color": "#000000", "space": "0"})
    for cell in second_row.cells:
        set_cell_border(cell, top={"sz": 4, "color": "#000000", "val": "single", "space": "0"})
    last_row = table.rows[-1]
    for cell in last_row.cells:
        set_cell_border(cell, top={"sz": 12, "val": "single", "color": "#000000", "space": "0"})
    return


def _generate_table2(data, document, table_count, name_dict):
    # 新建表格
    init_rows = 2
    init_cols = 9
    # table = document.add_table(rows=init_rows, cols=init_cols)
    table = create_table(document, init_rows, init_cols)
    # 1. 填充1-3行
    # 填充第一行表头
    row = table.rows[0]  # 表格
    f_cell = None
    for i in range(init_cols):  # 合并单元格
        if i == 0:
            f_cell = table.cell(0, 0)
        else:
            f_cell.merge(table.cell(0, i))
    frequency_table_name = ""
    row.cells[0].text = frequency_table_name + '结构方程模型路径系数检验'
    # 填充第二行
    table.cell(1, 0).merge(table.cell(1, 1)).merge(table.cell(1, 2)).text = "路径"
    table.cell(1, 3).text = "非标准化路径系数"
    table.cell(1, 4).text = "S.E."
    table.cell(1, 5).text = "C.R."
    table.cell(1, 6).text = "P"
    table.cell(1, 7).text = "标准化路径系数"
    table.cell(1, 8).text = "结论"
    # start_index = 2
    for k, v in data.item_dict.items():
        table.add_row()  # 表格动态增加一行
        cur_row = table.rows[-1]
        cur_row.cells[0].text = name_dict.get(v.from_name)
        cur_row.cells[1].text = "<---"
        cur_row.cells[2].text = name_dict.get(v.to_name)
        cur_row.cells[3].text = convert_str_to_float_3(v.est)
        cur_row.cells[4].text = convert_str_to_float_3(v.se)
        cur_row.cells[5].text = convert_str_to_float_3(v.z)
        cur_row.cells[6].text = add_p_value(v.p) if '' != add_p_value(v.p) else convert_str_to_float_3(v.p)
        cur_row.cells[7].text = convert_str_to_float_3(v.std_all)
        cur_row.cells[8].text = "成立" if v.p < 0.05 else "不成立"
    table.add_row()  # 表格动态增加一行
    cur_row = table.rows[-1]
    last_merge_cell = None
    for i in range(init_cols):  # 合并单元格
        if i == 0:
            last_merge_cell = cur_row.cells[0]
        else:
            last_merge_cell.merge(cur_row.cells[i])
    cur_row.cells[0].text = "Note:* refers to p<0.05； ** refers to p<0.01； *** refers to p<0.001。"
    format_table(table)
    add_three_lines_table2(table)
    return table


def _generate_table3(data, document, table_count):
    # 新建表格，item_dict中有总共的因子个数
    init_rows = 2 + len(data.item_dict)
    init_cols = 1 + len(data.item_dict)
    table = document.add_table(rows=init_rows, cols=init_cols)
    # 1. 填充1-3行
    # 填充第一行表头
    row = table.rows[0]  # 表格
    f_cell = None
    for i in range(init_cols):  # 合并单元格
        if i == 0:
            f_cell = table.cell(0, 0)
        else:
            f_cell.merge(table.cell(0, i))
    frequency_table_name = ""
    row.cells[0].text = frequency_table_name + '皮尔逊相关性与AVE平方根值'
    # 填充表头，及ave数据
    for i, v in enumerate(data.item_dict.keys()):
        table.cell(2 + i, 0).text = v
        table.cell(1, 1 + i).text = v
        table.cell(2 + i, 1 + i).text = convert_str_to_float_3(data.item_dict[v].ave_k_sq)
    # 填充表格 数据1
    key_list = list(data.factor_dict.keys())
    for index in range(len(key_list)):
        v = data.factor_dict.get(key_list[index])
        details = v.details
        for detail_index in range(len(details)):
            detail = details[detail_index]
            table.cell(3 + index + detail_index, 1 + index).text = convert_str_to_float_3(detail.std_all) + add_p_value(
                detail.p)
    # 最后加一行注释
    table.add_row()  # 表格动态增加一行
    cur_row = table.rows[-1]
    last_merge_cell = None
    for i in range(init_cols):  # 合并单元格
        if i == 0:
            last_merge_cell = cur_row.cells[0]
        else:
            last_merge_cell.merge(cur_row.cells[i])
    cur_row.cells[0].text = "Note:* refers to p<0.05； ** refers to p<0.01； *** refers to p<0.001。"
    return table


def convert_str_to_float_3(value) -> str:
    if not value:
        return ''
    if isinstance(value, str):
        if value.lower() == 'nan'.lower():
            return ''
        return "{:.3f}".format(float(value))
    elif isinstance(value, float):
        return "{:.3f}".format(value)
    return "{:.3f}".format(value)


def add_p_value(p):
    res = ''
    if p <= 0.001:
        res = '***'
    elif p <= 0.01:
        res = '**'
    elif p <= 0.05:
        res = '*'
    return res


def generate(src_data: [SEMResult], doc: Document = None, name_dict: dict = None) -> Document():
    if not doc:
        doc = Document()
    title1 = doc.add_heading(level=1)  # 增加标题
    t1_run = title1.add_run('结构模型')
    t1_run.font.color.rgb = RGBColor(10, 10, 10)
    _generate_report(src_data, doc, 1, name_dict)  # 生成表格
    return doc


if __name__ == '__main__':
    # 创建 Document 对象，等价于在电脑上打开一个 Word 文档
    doc = Document()
    pd.set_option('expand_frame_repr', False)

    pd.set_option('expand_frame_repr', False)
    df = pd.read_excel('./test_datas.xlsx')
    v_dict = dict()
    v_dict['F1'] = ["JG1", "JG2", "JG3", "JG4", "JG5"]
    v_dict['F2'] = ["XW1", "XW2", "XW3", "XW4"]
    v_dict['F3'] = ["JX1", "JX2", "JX3"]
    v_dict['F4'] = ["YY1", "YY2", "YY3"]
    X = ["F1", "F3"]  # 自遍历那个
    Y = ["F4"]  # 因变量
    M = ["F2"]  # 中介
    relations = list()

    for m in M:
        for x in X:
            relations.append(SEMRelationConfig(m, x))
    for y in Y:
        for x in X:
            relations.append(SEMRelationConfig(y, x))
    for y in Y:
        for m in M:
            relations.append(SEMRelationConfig(y, m))
    obj = SEM(df, v_dict, relations)
    src_data = obj.analysis()

    title1 = doc.add_heading(level=1)  # 增加标题
    t1_run = title1.add_run('结构模型')
    t1_run.font.color.rgb = RGBColor(10, 10, 10)
    _generate_report(src_data, doc, 1)  # 生成表格
    # 保存文档
    doc.save('demo.docx')
